/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package controller;

import entity.Accessory;
import entity.Phone;
import entity.Product;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import session.AccessoryFacade;
import session.PhoneFacade;
import session.ProductFacade;

/**
 *
 * @author Declan
 */
@WebServlet(name="CatalogueServlet", loadOnStartup = 1, urlPatterns={"/catalogue/*"})
public class CatalogueServlet extends HttpServlet {

    @EJB
    private ProductFacade productFacade;
    @EJB
    private PhoneFacade phoneFacade;
    @EJB
    private AccessoryFacade accessoryFacade;

    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        // Process request (Perform actions, set response attributes, set path for forward dispatch)
        String pathInfo = request.getPathInfo();
        pathInfo = (pathInfo == null) ? "" : pathInfo;
        String fdPath = null;
        Pattern p = Pattern.compile("/(\\d+)(/(\\w+))?"); // matches to /id/action
        Matcher m = p.matcher(pathInfo);
        m.find();
        Long productId;
        String action;
        try {
            productId = Long.parseLong(m.group(1));
        } catch (Exception ex) {
            productId = null;
        }
        try {
            action = m.group(3);
        } catch(IllegalStateException ex) {
            action = null;
        }

        ////////////////////////////////////////////////////////////////////////
        //CREATE
        if(pathInfo.equals("/phones/new")) {
            fdPath = "/WEB-INF/view/catalogue/createPhone.jsp";
        }
        ////////////////////////////////////////////////////////////////////////
        else if(pathInfo.equals("/accessories/new")) {
            fdPath = "/WEB-INF/view/catalogue/createAccessory.jsp";
        }
        ////////////////////////////////////////////////////////////////////////
        //READ
        else if (pathInfo.equals("")) {
            request.setAttribute("phones", phoneFacade.findAll());
            request.setAttribute("accessories", accessoryFacade.findAll());
            fdPath = "/WEB-INF/view/catalogue/default.jsp";
        }
        ////////////////////////////////////////////////////////////////////////
        else if (pathInfo.equals("/phones")) {
            request.setAttribute("phones", phoneFacade.findAll());
            fdPath = "/WEB-INF/view/catalogue/readPhones.jsp";
        }
        ////////////////////////////////////////////////////////////////////////
        else if (pathInfo.equals("/accessories")) {
            request.setAttribute("accessories", accessoryFacade.findAll());
            fdPath = "/WEB-INF/view/catalogue/readAccessories.jsp";
        }
        ////////////////////////////////////////////////////////////////////////
        else if(pathInfo.equals("/search")) {
            //Request process of search.
            StringTokenizer st = new StringTokenizer(request.getParameter("searchTerm"));
            ArrayList returnedProducts = new ArrayList();
            ArrayList returnedAccessories = new ArrayList();
            try{
                //Search each search term component
                while(st.hasMoreElements()){
                    String token = st.nextToken();
                    returnedProducts.addAll(phoneFacade.queryByManufacturerMake(token));
                    returnedAccessories.addAll(accessoryFacade.queryByManufacturerMakeType(token));
                }
                //Remove duplicates.
                ArrayList resultsProducts = new ArrayList();
                ArrayList resultsAccessories = new ArrayList();
                for(Object item : returnedProducts){
                    if(!resultsProducts.contains(item)) resultsProducts.add(item);
                }
                for(Object item : returnedAccessories){
                    if(!resultsAccessories.contains(item)) resultsAccessories.add(item);
                }
                request.setAttribute("products", resultsProducts);
                request.setAttribute("accessories", resultsAccessories);
            }
            catch(Exception ex){
                request.setAttribute("searchCatalogueFailureFlag", true);
            }
            fdPath = "/WEB-INF/view/catalogue/searchResults.jsp";
        }
        ////////////////////////////////////////////////////////////////////////
        else if (productId != null && action == null) {
            Product product = productFacade.find(productId);
            if(product != null){
                if(product instanceof Phone) {
                    Phone phone = (Phone)product;
                    request.setAttribute("phone", phone);
                    fdPath = "/WEB-INF/view/catalogue/viewPhone.jsp";
                }
                else if(product instanceof Accessory) {
                    Accessory accessory = (Accessory)product;
                    request.setAttribute("accessory", accessory);
                    fdPath = "/WEB-INF/view/catalogue/viewAccessory.jsp";
                }
            }
            else{
                request.setAttribute("faultyId", productId);
                fdPath = "/WEB-INF/view/catalogue/noSuchProduct.jsp";
            }
        }
        ////////////////////////////////////////////////////////////////////////
        // UPDATE
        else if (productId != null && action.equals("edit")) {
            Product product = productFacade.find(productId);
            if(product != null){
                if(product instanceof Phone) {
                    request.setAttribute("phone", product);
                    fdPath = "/WEB-INF/view/catalogue/updatePhone.jsp";
                }
                else if(product instanceof Accessory) {
                    request.setAttribute("accessory", product);
                    fdPath = "/WEB-INF/view/catalogue/updateAccessory.jsp";
                }
            }
            else{
                request.setAttribute("faultyId", productId);
                fdPath = "/WEB-INF/view/catalogue/noSuchProduct.jsp";
            }
        }
        ////////////////////////////////////////////////////////////////////////
        // DELETE
        else if (productId != null && action.equals("remove")) {
            Product product = productFacade.find(productId);
            if(product != null){
                request.setAttribute("product", product);
                fdPath = "/WEB-INF/view/catalogue/deleteProduct.jsp";
            }
            else{
                request.setAttribute("faultyId", productId);
                fdPath = "/WEB-INF/view/catalogue/noSuchProduct.jsp";
            }
        }
        
        ////////////////////////////////////////////////////////////////////////
        // Forward dispatch
        if(fdPath == null)
            fdPath = "/WEB-INF/jspf/error/404.jsp";

        request.getRequestDispatcher(fdPath).forward(request, response);
        
    } 

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        // Process request (Perform actions, set response attributes, set path for forward dispatch)
        String pathInfo = request.getPathInfo();
        pathInfo = (pathInfo == null) ? "" : pathInfo;
        String fdPath = null;
        Pattern p = Pattern.compile("/(\\d+)(/(\\w+))?"); // matches to /id/action
        Matcher m = p.matcher(pathInfo);
        m.find();
        Long productId;
        String action;
        try {
            productId = Long.parseLong(m.group(1));
        } catch (Exception ex) {
            productId = null;
        }
        try {
            action = m.group(3);
        } catch(IllegalStateException ex) {
            action = null;
        }

        //CREATE
        if(pathInfo.equals("/phones/new")) {
            // Add the phone to database
            Phone phone = new Phone(Double.parseDouble(request.getParameter("price")),
                                request.getParameter("manufacturer"),
                                request.getParameter("make"),
                                Float.parseFloat(request.getParameter("weight")));
            try {
                phoneFacade.create(phone);
                request.setAttribute("phoneName", phone.getName());
            } catch(Exception ex) {
                request.setAttribute("addPhoneFailureFlag", true);
            }
            fdPath = "/WEB-INF/view/catalogue/createPhone.jsp";
        }//
        else if(pathInfo.equals("/accessories/new")) {
            Accessory accessory = new Accessory(Double.parseDouble(request.getParameter("price")),
                    request.getParameter("accessoryType"),
                    request.getParameter("make"),
                    request.getParameter("manufacturer"));
            
            try {
                accessoryFacade.create(accessory);
                request.setAttribute("accessoryName", accessory.getName());
            } catch(Exception ex) {
                request.setAttribute("addAccessoryFailureFlag", true);
            }
            fdPath = "/WEB-INF/view/catalogue/createAccessory.jsp";
        }
        //READ
        else if (pathInfo.equals("")) {
            request.setAttribute("phones", phoneFacade.findAll());
            request.setAttribute("accessories", accessoryFacade.findAll());
            fdPath = "/WEB-INF/view/catalogue/default.jsp";
        }
        else if (pathInfo.equals("/phones")) {
            request.setAttribute("phones", phoneFacade.findAll());
            fdPath = "/WEB-INF/view/catalogue/readPhones.jsp";
        }
        else if (pathInfo.equals("/accessories")) {
            request.setAttribute("accessories", accessoryFacade.findAll());
            fdPath = "/WEB-INF/view/catalogue/readAccessories.jsp";
        }
        else if (productId != null && action == null) {
            Product product = productFacade.find(productId);
            if(product != null){
                if(product instanceof Phone) {
                    Phone phone = (Phone)product;
                    request.setAttribute("phone", phone);
                    fdPath = "/WEB-INF/view/catalogue/viewPhone.jsp";
                }
                else if(product instanceof Accessory) {
                    Accessory accessory = (Accessory)product;
                    request.setAttribute("accessory", accessory);
                    fdPath = "/WEB-INF/view/catalogue/viewAccessory.jsp";
                }
            }
            else{
                request.setAttribute("faultyId", productId);
                fdPath = "/WEB-INF/view/catalogue/noSuchProduct.jsp";
            }
        }
        // UPDATE
        else if (productId != null && action.equals("edit")) {
            Product product = productFacade.find(productId);
            if(product != null){
                if(product instanceof Phone) {
                    try {
                        // Edit Phone entity with updated data
                        Phone phone = (Phone) product;
                        phone.setManufacturer(request.getParameter("manufacturer"));
                        phone.setMake(request.getParameter("make"));
                        phone.setPrice(Double.parseDouble(request.getParameter("price")));
                        phone.setWeight(Float.parseFloat(request.getParameter("weight")));
                        // Merge new phone entity with existing record with productId
                        phoneFacade.edit(phone);
                        request.setAttribute("phoneName", phone.getName());
                        request.setAttribute("phone", phone);
                    }
                    catch (Exception ex) {
                        request.setAttribute("updatePhoneFailureFlag", true);
                    }
                    fdPath = "/WEB-INF/view/catalogue/updatePhone.jsp";
                }
                else if(product instanceof Accessory) {
                    try {
                        // Edit Phone entity with updated data
                        Accessory accessory = (Accessory) product;
                        accessory.setManufacturer(request.getParameter("manufacturer"));
                        accessory.setMake(request.getParameter("make"));
                        accessory.setPrice(Double.parseDouble(request.getParameter("price")));
                        accessory.setAccessoryType(request.getParameter("accessoryType"));
                        // Merge new phone entity with existing record with productId
                        accessoryFacade.edit(accessory);
                        request.setAttribute("accessoryName", accessory.getName());
                        request.setAttribute("accessory", accessory);
                    }
                    catch (Exception ex) {
                        request.setAttribute("updateAccessoryFailureFlag", true);
                    }
                    fdPath = "/WEB-INF/view/catalogue/updateAccessory.jsp";
                }
            }
            else{
                request.setAttribute("faultyId", productId);
                fdPath = "/WEB-INF/view/catalogue/noSuchProduct.jsp";
            }
        }
        // DELETE
        else if (productId != null && action.equals("remove")) {
            Product product = productFacade.find(productId);
            if(product != null){
                try {
                    String productName = product.getName();
                    productFacade.remove(product);
                    request.setAttribute("deletedProductName", productName);
                }
                catch(Exception ex) {
                    request.setAttribute("deleteProductFailureFlag", true);
                }
                fdPath = "/WEB-INF/view/catalogue/deleteProduct.jsp";
            }
            else{
                request.setAttribute("faultyId", productId);
                fdPath = "/WEB-INF/view/catalogue/noSuchProduct.jsp";
            }
        }
        ////////////////////////////////////////////////////////////////////////
        // Forward dispatch
        if(fdPath == null)
            fdPath = "/WEB-INF/jspf/error/404.jsp";

        request.getRequestDispatcher(fdPath).forward(request, response);
        
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Servlet to handle all requests with URL /catalogue/*";
    }// </editor-fold>

}
